﻿using System;
using System.Windows.Forms;
using GameStructure.Core;
using GameStructure.GaneState;
using GameStructure.Types;
using GameStructure.Utilities;
using Tao.DevIl;
using Tao.OpenGl;

namespace GameStructure
{
    public partial class Form1 : Form
    {
        private FastLoop _fastLoop;
        private bool _fullscreen = false;
        private readonly StateSystem _system = new StateSystem();
        private readonly TextureManager _textureManager = new TextureManager();
        private Input _input = new Input();

        public Form1()
        {
            _fastLoop = new FastLoop(GameLoop);

            InitializeComponent();
            _openGlControl.InitializeContexts();

            // Init DevIl
            Il.ilInit();
            Ilu.iluInit();
            Ilut.ilutInit();
            Ilut.ilutRenderer(Ilut.ILUT_OPENGL);

            // Load textures
            _textureManager.LoadTexture("font", "Resources/font.tga");
            _textureManager.LoadTexture("face", "Resources/face.tif");
            _textureManager.LoadTexture("face_alpha", "Resources/face_alpha.tif");
            

            if (_fullscreen)
            {
                FormBorderStyle = FormBorderStyle.None;
                WindowState = FormWindowState.Maximized;
            }
            else
            {
                ClientSize = new System.Drawing.Size(1280, 720);
            }

            // Add all the states that will be used.
            //_system.AddState("splash", new SplashScreenState(_system));
            //_system.AddState("title_menu", new TitleMenuState());
            //_system.AddState("sprite_test", new DrawSpriteState(_textureManager));
            //_system.AddState("sprite_class_test", new TestSpriteClassState(_textureManager));
            //_system.AddState("text_state", new TextTestState(_textureManager));
            //_system.AddState("text_render_state", new TextRenderState(_textureManager));
            //_system.AddState("fps_state", new FPSTestState(_textureManager));
            //_system.AddState("text_wrap_state", new TestWrappedTextState(_textureManager));
            //_system.AddState("graph_state", new WaveformGraphState());
            //_system.AddState("special_effect_state", new SpecialEffectState(_textureManager));
            //_system.AddState("circle_intersect_state", new CircleIntersectionState(_input));
            //_system.AddState("rectangle_intersect_state", new RectangleIntersectionState(_input));
            //_system.AddState("sprite_tween_state", new TweenTestState(_textureManager));
            _system.AddState("matrix_state", new MatrixTestState(_textureManager));

            // select the start state.
            _system.ChangeState("matrix_state");

            Setup2DGraphics(ClientSize.Width, ClientSize.Height);
        }

        private void GameLoop(double elapsedTime)
        {
            UpdateInput();
            _system.Update(elapsedTime);
            _system.Render();
            _openGlControl.Refresh();
        }

        private void UpdateInput()
        {
            System.Drawing.Point mousePos = Cursor.Position;
            mousePos = _openGlControl.PointToClient(mousePos);

            // Now use our point definition.
            var adjustedMousePoint = new Point
            {
                X = mousePos.X - ((float) ClientSize.Width/2),
                Y = ((float) ClientSize.Height/2) - mousePos.Y
            };
            _input.MousePosition = adjustedMousePoint;
        }

        private void Setup2DGraphics(double width, double height)
        {
            var halfWidth = width/2;
            var halfHeight = height/2;
            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            Gl.glOrtho(-halfWidth, halfWidth, -halfHeight, halfHeight, -100, 100);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();
        }

        protected override void OnClientSizeChanged(EventArgs e)
        {
            base.OnClientSizeChanged(e);
            Gl.glViewport(0, 0, ClientSize.Width, ClientSize.Height);
            Setup2DGraphics(ClientSize.Width, ClientSize.Height);
        }
    }
}
